/*
\ brief:  实现文件
\ author: 清晨与猫鱼
*/
#include <iostream>     // 标准输入输出库
#include <list>         // list容器
#include <memory>       // 内存管理文件

using namespace std;        


/*
\ brief :   包装抽象接口类
\ author : 清晨与猫鱼
*/
class Packing {
public:
    virtual string pack() = 0;      // 接口函数 包装材质
};


/*
\ brief :  商品项抽象接口类
\ author : 清晨与猫鱼
*/
class Item {
public:
    virtual string name() = 0;      // 接口函数 商品名称
    virtual unique_ptr<Packing> packing() = 0;      // 接口函数，返回包装材质的实例对象
    virtual float price() = 0;          // 接口函数计算价格
};


/*
\ brief :   包装纸
\ author : 清晨与猫鱼
*/
class Wrapper 
    : public Packing {
public:
    string pack() {
        return "Wrapper";
    }
};



/*
\ brief :   瓶装
\ author : 清晨与猫鱼
*/
class Bottle 
    : public Packing {
public:
    string pack() {
        return "Bottle";
    }
};



/*
\ brief :   汉堡抽象接口类
\ author : 清晨与猫鱼
*/
class Burger 
    : public Item {
public:
    unique_ptr<Packing> packing() {
        return make_unique<Wrapper>();
    }
};



/*
\ brief :  冷饮抽象接口类
\ author : 清晨与猫鱼
*/
class ColdDrink 
    : public Item {
public:
    unique_ptr<Packing> packing() {
        return make_unique<Bottle>();
    }
};


/*
\ brief :   蔬菜汉堡
\ author : 清晨与猫鱼
*/
class VegBurger 
    : public Burger {
public:
    float price() {
        return 25.0f;
    }

    string name() {
        return "Veg Burger";
    }
};


/*
\ brief :   鸡肉汉堡
\ author : 清晨与猫鱼
*/
class ChickenBurger 
    : public Burger {
public:
    float price() {
        return 50.5f;
    }

    string name() {
        return "Chicken Burger";
    }
};


/*
\ brief :   可口可乐
\ author : 清晨与猫鱼
*/
class Coke 
    : public ColdDrink {
public:
    float price() {
        return 30.0f;
    }

    string name() {
        return "Coke";
    }
};



/*
\ brief :  百世可乐
\ author : 清晨与猫鱼
*/
class Pepsi 
    : public ColdDrink {
public:
    float price() {
        return 35.0f;
    }

    string name() {
        return "Pepsi";
    }
};


/*
\ brief :   进餐
\ author : 清晨与猫鱼
*/
class Meal {
public:
/*
\ brief:  添加点餐的食物商品项
\ author: 清晨与猫鱼
*/
    void addItem(Item* item) {
        items.emplace_back(item);
    }

/*
\ brief:  计算饭钱
\ author: 清晨与猫鱼
*/
    float getCost() {
        float cost = 0.0f;
        for(auto& item : items) {
            cost += item->price();
        }
        return cost;
    }

/*
\ brief:  打印点餐的信息
\ author: 清晨与猫鱼
*/
    void showItems() {
        for(auto& item : items) {
            cout << "Item : " << item->name() << endl;
            cout << "Packing : " << item->packing()->pack() << endl;
            cout << "Price : " << item->price() << endl;
        }
    }
private:
    list<unique_ptr<Item>> items;       // 商品项容器
};


/*
\ brief:  进餐建设者
\ author: 清晨与猫鱼
*/
class MealBuilder {
public:

/*
\ brief :  蔬菜汉堡套餐
\ author : 清晨与猫鱼
*/
    static Meal* prepareVegMeal() {
        Meal* meal = new Meal;
        meal->addItem(new VegBurger);
        meal->addItem(new Coke);
        return meal;
    }

/*
\ brief:  鸡肉汉堡套餐
\ author: 清晨与猫鱼
*/
    static Meal* prepareNonVegMeal() {
        Meal* meal = new Meal;
        meal->addItem(new ChickenBurger);
        meal->addItem(new Pepsi);
        return meal;
    }

};